﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef ITEMVIEW_VALIDATE_HELPER_H
#define ITEMVIEW_VALIDATE_HELPER_H

#include "GmUiCommonComponent.h"

#include <QStyledItemDelegate>
#include <unordered_map>

namespace gcmp
{

class ValidatorBase;

// 继承QAbstractItemView的控件上输入验证可以使用该类
class GM_UI_COMMON_COMPONENT_EXPORT ItemViewValidateHelper : public QStyledItemDelegate
{
    Q_OBJECT

private:
    // ViewEventFilter辅助处理情况：
    // 输入非法时，鼠标点击其他格子后，上下左右键会导致currentIndex变化
    // 不处理会导致当输入变合法后按Tab没有反应
    class ViewEventFilter : public QObject
    {
    public:
        explicit ViewEventFilter(ItemViewValidateHelper* pDelegate);
        bool eventFilter(QObject* pWatched, QEvent* pEvent) override;

    private:
        friend class ItemViewValidateHelper;
        ItemViewValidateHelper* m_pDelegate;
    };

public:
    explicit ItemViewValidateHelper(const QColor& color, QAbstractItemView* pParent = nullptr);

    QWidget* createEditor(QWidget* pParent, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
    void destroyEditor(QWidget* pEditor, const QModelIndex& index) const override;

    void setEditorData(QWidget* pEditor, const QModelIndex& index) const override;

    bool editorEvent(QEvent* pEvent, QAbstractItemModel* pModel, const QStyleOptionViewItem& option, const QModelIndex& index) override;
    bool eventFilter(QObject* pWatched, QEvent* pEvent) override;

    QAbstractItemView* GetParentItemView() const;

    // 列配置验证器
    void SetValidatorsForColumns(int validatorIdRole, const std::unordered_map<std::wstring, const ValidatorBase*>& validators);
    const ValidatorBase* GetValidatorForColumn(int column) const;

    // 网格配置验证器
    void SetValidatorsForCell(const QMap<QModelIndex, const ValidatorBase*>& validators);
    const ValidatorBase* GetValidatorForCell(const QModelIndex& cell) const;

signals:
    // 验证一次就会触发一次，和上次状态可能一样
    void validStateUpdated(const QModelIndex& index, bool valid);

private:
    void OnTextEdited();
    void OnEditingFinished();

    const ValidatorBase* GetCurrentValidator() const;
    void Validate(QLineEdit* pEdit, bool editingFinished);
    bool Validate(const QLineEdit *pEdit) const;

    void DisableHeaderClickable() const;
    void RestoreHeaderClickable() const;

private:
    QColor m_color;
    QAbstractItemView* m_pView;
    bool m_editingValueIsValid;
    mutable QModelIndex m_editingIndex;
    mutable int m_viewSelectionMode;
    mutable int m_viewFocusPolicy;
    mutable bool m_viewHorizontableHeaderClickable;
    mutable bool m_viewVerticalHeaderClickable;

    int m_validatorIdRole;
    std::unordered_map<std::wstring, const ValidatorBase*> m_columnValidators;
    QMap<QModelIndex, const ValidatorBase*> m_cellValidators;
};

}   // end namespace gcmp

#endif // ITEMVIEW_VALIDATE_HELPER_H
